package com.only4play.practice.ordercenter.core.service.impl;

import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.only4play.codegen.support.constants.ValidStatus;
import com.only4play.practice.common.OrderErrorCode;
import com.only4play.practice.common.enums.OrderState;
import com.only4play.practice.common.exception.BizException;
import com.only4play.practice.common.model.RespWrapper;
import com.only4play.practice.ordercenter.api.model.domainmodel.OrderCreateModel;
import com.only4play.practice.ordercenter.core.entity.OrderBase;
import com.only4play.practice.ordercenter.core.mapper.OrderBaseMapper;
import com.only4play.practice.ordercenter.core.service.IOrderBaseService;
import com.only4play.practice.ordercommon.pay.PayItem;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Collections;

/**
    * <p>
    *  服务实现类
    * </p>
*
* @author mdy
* @since 2024-09-13
*/
@Service
@Slf4j
public class OrderBaseServiceImpl extends ServiceImpl<OrderBaseMapper, OrderBase> implements IOrderBaseService {


    @Autowired
    private ApplicationEventPublisher eventPublisher;
    /**
     * 创建业务订单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RespWrapper<Long> createOrder(OrderCreateModel createModel) {

        log.info("[新增业务订单] 入参 = {}", createModel);

        // OrderCreateModel  ->  OrderBase
        OrderBase orderBase = new OrderBase();
        BeanUtils.copyProperties(createModel, orderBase);

        // TODO 校验订单参数
        Assert.notEmpty(createModel.getItemInfoList());
        // 遍历订单项，合计订单总金额
//        Long itemTotal = createModel.getItemInfoList().stream().mapToLong(OrderItemModel::getRealAmount).sum();
//        orderBase.setTotalAmount(itemTotal);
        // TODO 生成当前系统的订单号

        // TODO 生成当前系统的流水号 （跟支付通道关联）
        Long flowNo = System.currentTimeMillis();
        orderBase.setFlowNo(flowNo);
        // 业务属性赋值处理 初始化订单状态
        orderBase.setValidStatus(ValidStatus.VALID);
        orderBase.setInvoiceFlag(ValidStatus.INVALID);
        Long total = orderBase.getTotalAmount();
        // payList中有没有虚拟资产、优惠券抵扣
        if (!IterUtil.isEmpty(createModel.getPayList())) {

            orderBase.setPayList(createModel.getPayList());
            BigDecimal hasPay = orderBase.getPayList().stream().map(PayItem::getMoney)
                    .reduce(BigDecimal.ZERO, NumberUtil::add);
            if (NumberUtil.isGreater(hasPay, BigDecimal.valueOf(total))) {
                throw new BizException(OrderErrorCode.PAY_TOO_BIG);
            }else if(NumberUtil.equals(hasPay,total)){
                orderBase.setOrderState(OrderState.SUCCESS);
                orderBase.setWaitPay(0L);
            }else {
                orderBase.setOrderState(OrderState.WAITING);
                orderBase.setWaitPay(NumberUtil.sub(total,hasPay).longValue());
            }
        } else {
            //没有虚拟资产抵扣
            orderBase.setPayList(Collections.EMPTY_LIST);
            if (NumberUtil.equals(total, BigDecimal.ZERO)) {
                orderBase.setOrderState(OrderState.SUCCESS);
                orderBase.setWaitPay(0L);
            } else {
                orderBase.setWaitPay(total);
                orderBase.setOrderState(OrderState.WAITING);
            }
        }

        // 解耦： 发布同步事件（支持事务） 或者 直接用异步（不支持事务）
//        eventPublisher.publishEvent(new OrderEvents.OrderCreateEvent(orderBase, createModel));

        // TODO 订单入库 【落库时注意将来可能要区分To B 、To C || 分库分表 || 主从表】

        // 发送MQ || 放入上下文 || 存入Redis || 直接将订单信息返回

        baseMapper.insert(orderBase);
        log.info("[新增业务订单] 订单入库完成 orderVO = {}",orderBase);
        return RespWrapper.success(null);
    }


}
